package com.sojson.util;

import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import lombok.extern.slf4j.Slf4j;

/**
 * 线程相关工具类
 *
 * @author liu
 * @date 2021-11-09
 */
@Slf4j
public class ThreadUtil {

    /**
     * 获取线程名称
     *
     * @return
     */
    public static String getName() {
        return Thread.currentThread().getName();
    }

    /**
     * 设置线程名称
     *
     * @param name
     */
    public static void setName(String name) {
        Thread.currentThread().setName(name);
    }

    /**
     * 创建线程池
     *
     * @param name
     * @param size
     * @return
     */
    public static ScheduledExecutorService creThreadPool(String name, int size) {
        return Executors.newScheduledThreadPool(size, getThreadFactory(name));
    }

    /**
     * 获取线程工厂
     *
     * @param name
     * @return
     */
    public static ThreadFactory getThreadFactory(String name) {
        AtomicInteger threadNumber = new AtomicInteger(1);
        return new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(name + threadNumber.getAndIncrement());
                t.setDaemon(true);
                return t;
            }
        };
    }

    /**
     * 获取线程工厂
     *
     * @param name
     * @return
     */
    public static ThreadFactory getThreadFactoryNotNum(String name, int coreSize, int maxSize) {
        int mSize = maxSize * 2;
        AtomicInteger threadNumber = new AtomicInteger(1);
        return new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                if (threadNumber.get() >= mSize) {
                    threadNumber.set(1);
                }
                Thread t = new Thread(r);
                t.setName(name + threadNumber.getAndIncrement());
                t.setDaemon(true);
                return t;
            }
        };
    }

    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            return;
        }
    }

    /**
     * 打印线程异常信息
     */
    public static void printException(Runnable r, Throwable t) {
        if (t == null && r instanceof Future<?>) {
            try {
                Future<?> future = (Future<?>)r;
                if (future.isDone()) {
                    future.get();
                }
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            log.error(t.getMessage(), t);
        }
    }

    /**
     * 获取所有调用了当前方法的方法信息
     */
    public static void getAllInvokMethod() {
        StackTraceElement[] s = new Exception().getStackTrace();
        int i = 2, size = s.length;
        for (; i < size; i++) {
            String className = s[i].getClassName();
            if (className.startsWith("org.springframework.web")) {
                return;
            }
            String getMethodName = s[i].getMethodName();
            int lineNum = s[i].getLineNumber();
            System.out.println("class==" + className + ":method==" + getMethodName + ":行数==" + lineNum);
        }
    }

    /**
     * 获取最近的调用了当前方法的方法信息
     */
    public static void getInvokMethod() {
        getInvokMethod(3);
    }

    /**
     * 获取距离当前方法的第N个调用了当前方法的方法信息
     *
     * @param n 第几个方法
     */
    public static void getInvokMethod(int n) {
        StackTraceElement[] s = new Exception().getStackTrace();
        String getMethodName = s[n + 1].getMethodName();
        String className = s[n + 1].getClassName();
        int lineNum = s[n + 1].getLineNumber();
        System.out.println("class==" + className + ":method==" + getMethodName + ":行数==" + lineNum);
    }

    /**
     * 获取距离当前方法的第N个调用了当前方法的方法信息
     *
     * @param n 第几个方法
     */
    public static void getInvokMethod(int... n) {
        StackTraceElement[] s = new Exception().getStackTrace();
        int i = 0, size = n.length;
        for (; i < size; i++) {
            String getMethodName = s[n[i] + 1].getMethodName();
            String className = s[n[i] + 1].getClassName();
            int lineNum = s[n[i] + 1].getLineNumber();
            System.out.println("class==" + className + ":method==" + getMethodName + ":行数==" + lineNum);
        }
    }

    /**
     * 获取距离当前方法的第start个后的size个调用了当前方法的方法信息
     *
     * @param start 开始方法的数量
     * @param size 查多少个
     */
    public static void getInvokMethod(int start, int size) {
        StackTraceElement[] s = new Exception().getStackTrace();
        start += 1;
        size += start;
        for (; start < size; start++) {
            String getMethodName = s[start].getMethodName();
            String className = s[start].getClassName();
            int lineNum = s[start].getLineNumber();
            System.out.println("class==" + className + ":method==" + getMethodName + ":行数==" + lineNum);
        }
    }

    /**
     * 获取当前类的包的地址
     *
     * @param obj
     */
    public static void getClassPackage(Class<?> cla) {
        ProtectionDomain pd = cla.getProtectionDomain();

        CodeSource cs = pd.getCodeSource();

        String url = cs.getLocation().toString();
        System.out.println(url.substring(url.indexOf("/") + 1));
    }

}